#include "Board.h"

#include <iostream>
#include <map>
#include <string>

#include "../common/general/Constantes.h"
#include "Candy.h"

Board::Board() {
    set_border_width(10);

	// Conecto las señales para cuando se suelta un item
	targetList.push_back(Gtk::TargetEntry("ITEM"));
    drag_dest_set(targetList);
    this->signal_drag_data_received().connect(sigc::mem_fun(*this,
											  &Board::dropItem));
}

Board::~Board() { }

std::map<std::pair<int, int>, Candy *> *Board::getImagenes() {
    return &imagenes;
}

void Board::setImagenes(std::map<std::pair<int, int>, Candy*>* imagenes) {
	std::map<std::pair<int, int>, Candy*>::iterator it;
	
	for (it = imagenes->begin(); it != imagenes->end(); it++) {
		std::pair<int, int> posicion = it->first;
		Candy* candy = it->second;
		
		/* Valido las fichas que se pueden mantener, para el caso que haya 
		 * cambiado el tamaño del tablero
		 */
		if (posicion.first < cantFilas && posicion.second < cantColumnas) {
			int posX, posY;
			
			mapPosition(posX, posY, posicion.first, posicion.second);
			
			addCandy(candy, posX, posY, true);
		}else {
			this->imagenes.erase(it);
		}
	}
}

void Board::setBoardSize(int cantFilas, int cantColumnas) {
	this->cantFilas = cantFilas;
	this->cantColumnas = cantColumnas;
	
    /* Elimino todos los hijos para redibujar el tablero. */
    Glib::ListHandle<Widget*> childList = this->get_children();
    Glib::ListHandle<Widget*>::iterator it = childList.begin();

    /* Limpio todos los divisores y las candy puestas */
    while (it != childList.end()) {
        Widget* widget = *it;
        remove(*widget);
        it++;
    }

    /* Guardo los datos del tablero */
    width = cantColumnas * 40;
    height = cantFilas * 40;

    // Dibujo las divisiones horizontales
    for (int i = 0; i <= cantFilas; i++) {
        Gtk::HSeparator* separador = manage(new Gtk::HSeparator());
        separador->set_size_request(width, 10);
        put(*separador, 0, i * 40);
        show_all();
    }

    // Dibujo las divisiones verticales
    for (int i = 0; i <= cantColumnas; i++) {
        Gtk::VSeparator *separador = manage(new Gtk::VSeparator());
        separador->set_size_request(10, height);
        put(*separador, i * 40, 0);
        show_all();
    }
}

void Board::dropItem(const Glib::RefPtr<Gdk::DragContext> &context, int x,
                     int y, const Gtk::SelectionData &selection_data, 
                     guint info, guint time) {
    std::string itemType = selection_data.get_data_as_string();
	std::string ruta;
	
	// Valido que lo haya soltado adentro del tablero
    if (x > width || y > height) {
        return;
    }

    Candy* candy = NULL;
	
	// Veo el tipo de item a agregar al tablero
    if (itemType.compare(BLUE_BUTTON) == 0) {
        ruta = RUTA_BLUE_BUTTON;
    }else if (itemType.compare(GREEN_BUTTON) == 0) {
        ruta = RUTA_GREEN_BUTTON;
    }else if (itemType.compare(RED_BUTTON) == 0) {
        ruta = RUTA_RED_BUTTON;
    }else if (itemType.compare(VIOLET_BUTTON) == 0) {
        ruta = RUTA_VIOLET_BUTTON;
    }else if (itemType.compare(YELLOW_BUTTON) == 0) {
        ruta = RUTA_YELLOW_BUTTON;
    }else if (itemType.compare(BLUE_MINIBAR_H) == 0) {
        ruta = RUTA_BLUE_MINIBAR_H;
    }else if (itemType.compare(GREEN_MINIBAR_H) == 0) {
        ruta = RUTA_GREEN_MINIBAR_H;
    }else if (itemType.compare(RED_MINIBAR_H) == 0) {
        ruta = RUTA_RED_MINIBAR_H;
    }else if (itemType.compare(VIOLET_MINIBAR_H) == 0) {
        ruta = RUTA_VIOLET_MINIBAR_H;
    }else if (itemType.compare(YELLOW_MINIBAR_H) == 0) {
        ruta = RUTA_YELLOW_MINIBAR_H;
    }else if (itemType.compare(BLUE_MINIBAR_V) == 0) {
        ruta = RUTA_BLUE_MINIBAR_V;
    }else if (itemType.compare(GREEN_MINIBAR_V) == 0) {
        ruta = RUTA_GREEN_MINIBAR_V;
    }else if (itemType.compare(RED_MINIBAR_V) == 0) {
        ruta = RUTA_RED_MINIBAR_V;
    }else if (itemType.compare(VIOLET_MINIBAR_V) == 0) {
        ruta = RUTA_VIOLET_MINIBAR_V;
    }else if (itemType.compare(YELLOW_MINIBAR_V) == 0) {
        ruta = RUTA_YELLOW_MINIBAR_V;
    }else if (itemType.compare(GOLDENSTAR) == 0) {
        ruta = RUTA_GOLDENSTAR;
    }else {
		ruta = RUTA_HUECO;
	}

	candy = manage(new Candy(ruta, itemType));
    addCandy(candy, x, y, false);
}

void Board::mapCoordinates(int x, int y, int &fila, int &columna) {
    fila = x / 40;
    columna = y / 40;
}

void Board::mapPosition(int &x, int &y, int fila, int columna) {
    x = fila * 40 + 5;
    y = columna * 40 + 5;
}

void Board::addCandy(Candy* candy, int x, int y, bool cargando) {
    int fila, columna;
    int posX, posY;

    mapCoordinates(x, y, fila, columna);
    mapPosition(posX, posY, fila, columna);
	
    // Si ya hay una imagen, la elimino.
    if (imagenes.find(std::pair<int, int>(fila, columna)) != imagenes.end()) {
        Candy* imagen = imagenes[std::pair<int, int>(fila, columna)];
        
		// Sino lo intenta eliminar y tira error
		if (!cargando) {
			remove(*imagen);
		}
    }

    imagenes[std::pair<int, int>(fila, columna)] = candy;
    put(*candy, posX, posY);

    show_all();
}
